package org.ns.longhttp;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import org.ns.longhttp.config.ServerConfig;
import org.ns.longhttp.handler.asynchandler.AsyncResponseHandler;
import org.ns.longhttp.handler.HttpServerReaderHandler;
import org.ns.longhttp.selector.datamapper.DataMappingQueue;
import org.ns.longhttp.selector.requestmapper.RequestMappingQueue;

public class Server {
    private int port;
    private int maxConnection = 10000;
    private int maxContentLength = 1024 * 1024 * 100;
    // 请求的映射队列。用于挂起所有GET请求。
    private RequestMappingQueue requestQueue = new RequestMappingQueue();
    // 数据映射队列，用于暂存post的数据
    private DataMappingQueue dataqueue = new DataMappingQueue();
    // 异步应答处理服务，用于将数据应答给挂起的请求的客户端。
    private AsyncResponseHandler asyncHandler = new AsyncResponseHandler(dataqueue, requestQueue);
    // 服务器的配置
    private ServerConfig serverConfig = ServerConfig.DEFAULT_CONFIG;

    public Server(int port) {
        this(port, ServerConfig.DEFAULT_CONFIG);
    }

    public Server(int port, ServerConfig serverConfig) {
        this.port = port;
        this.serverConfig = serverConfig;
        this.init();
        this.start();
    }
    // 初始化配置
    private void init() {
        if (serverConfig != null) {
            dataqueue.config(serverConfig);
            requestQueue.config(serverConfig);
            asyncHandler.config(serverConfig);
        }
    }

    private void start() {
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap b = new ServerBootstrap();
        b.group(boss, worker);
        b.option(ChannelOption.SO_BACKLOG, maxConnection);
        b.childOption(ChannelOption.SO_KEEPALIVE, true);
        b.channel(NioServerSocketChannel.class);
        b.childHandler(new ChannelInitializer<SocketChannel>() {

            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new HttpServerCodec());
                pipeline.addLast(new HttpObjectAggregator(maxContentLength));
                pipeline.addLast(new HttpServerReaderHandler(requestQueue, dataqueue, asyncHandler));
            }
        });

        try {
            ChannelFuture bind = b.bind(port).sync();
            bind.channel().closeFuture().sync();
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }

    }
}
